﻿using System;
using System.Collections.Generic;
using System.Text;

using MiP.Common;

namespace MiP.Xml.Core.StringEvaluation
{
    internal class EvaluationContext
    {
        private readonly string _sourceString;

        private EvaluationState _state = new ReadToDollarEvaluationState();
        private int _index;

        public EvaluationContext(string sourceString, IDictionary<string, string> variables, ILogger logger)
            : this(sourceString, variables, logger, new HashSet<string>())
        {
        }

        public EvaluationContext(string sourceString, IDictionary<string, string> variables, ILogger logger, HashSet<string> currentOpenVariables)
        {
            if (logger == null)
                throw new ArgumentNullException("logger");

            _sourceString = sourceString;
            Logger = logger;
            Variables = variables;
            Result = new StringBuilder();
            VariableName = new StringBuilder();
            Incomplete = new StringBuilder();
            CurrentOpenVariables = currentOpenVariables;
        }

        public ILogger Logger
        {
            get;
            private set;
        }

        public IDictionary<string, string> Variables
        {
            get;
            private set;
        }

        public StringBuilder Result
        {
            get;
            private set;
        }

        public StringBuilder VariableName
        {
            get;
            private set;
        }

        public StringBuilder Incomplete
        {
            get;
            private set;
        }

        public HashSet<string> CurrentOpenVariables
        {
            get;
            private set;
        }

        public string Evaluate()
        {
            while (_index < _sourceString.Length)
            {
                _state = _state.Next(this);
            }

            if (Incomplete.Length>0)
                Result.Append(Incomplete); // TODO: refactor this into a EndOfStringReachedEvaluationState

            return Result.ToString();
        }

        public char ReadNextChar()
        {
            char result = _sourceString[_index++];
            return result;
        }
    }
}